---
id: introduction
title: Introduction
sidebar_label: Introduction
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeDemo from '@site/src/components/CodeDemo';

## What is Angular Three (NGT)?

NGT is a custom **Renderer** that renders [THREE.js](https://threejs.org) entities instead of DOM elements.
Developers can leverage their [Angular](https://angular.io) skills to build 3D scenes declaratively by tapping into
Angular features.

:::tip
It is recommended that developers should get familiar with both Angular and THREE.js before starting with NGT
:::

## What is the difference between NGT and React Three Fiber (R3F)?

Fundamentally, NGT and [R3F](https://docs.pmnd.rs/react-three-fiber/getting-started/introduction) are both custom renderers.
Technically, there are differences between Angular Renderer and React Reconciler. That said, R3F is a huge inspiration for NGT.
Many code from R3F are brought over to NGT and adjusted to work with Angular. NGT APIs are intentionally left similar to those from R3F
so that developers who have experience with R3F can also work with NGT without much friction.

## Why a Renderer?

In the past, Angular Three was a **Component Library** via the name `@angular-three/core`. However, a **Component Library** suffers greatly
from frequent THREE.js updates. There are trade-offs but Angular Three decides to take the approach of a **Renderer** to ensure optimal compatibilities
with THREE.js as well as maintenance cost over the time.

## What does the code look like?

:::info
Play with a Scene with a re-useable component which has its own states, events, and inputs

<CodeDemo srcId="zgmtpe" />
:::

<Tabs>

<TabItem value="appComponentTs" label="app.component.ts" default>

```ts
import { Component } from '@angular/core';
import { Scene } from './scene.component';
import { NgtCanvas } from 'angular-three';

@Component({
    selector: 'my-app',
    standalone: true,
    template: `<ngt-canvas [sceneGraph]="Scene" />`,
    imports: [NgtCanvas],
})
export class AppComponent {
    readonly Scene = Scene;
}
```

</TabItem>

<TabItem value="sceneComponentTs" label="scene.component.ts">

```ts
import { Component, CUSTOM_ELEMENTS_SCHEMA, Input, signal } from '@angular/core';
import { extend } from 'angular-three';
import { AmbientLight, BoxGeometry, Mesh, MeshStandardMaterial, PointLight } from 'three';

extend({ Mesh, MeshStandardMaterial, BoxGeometry, AmbientLight, PointLight });

@Component({
    selector: 'demo-cube',
    standalone: true,
    templateUrl: 'cube.component.html',
    schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class Cube {
    @Input() position = [0, 0, 0];

    hovered = signal(false);
    active = signal(false);

    onBeforeRender(cube: Mesh) {
        cube.rotation.x += 0.01;
        cube.rotation.y += 0.01;
    }
}

@Component({
    standalone: true,
    templateUrl: 'scene.component.html',
    imports: [Cube],
    schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class Scene {}
```

</TabItem>

<TabItem value="sceneComponentHtml" label="scene.component.html">

```html
<ngt-ambient-light />
<ngt-point-light [position]="10" />
<demo-cube [position]="[1.5, 0, 0]" />
<demo-cube [position]="[-1.5, 0, 0]" />
```

</TabItem>

<TabItem value="cubeHtml" label="cube.component.html">

```html
<ngt-mesh
    [position]="position"
    [scale]="active() ? 1.5 : 1"
    (click)="active.set(!active())"
    (pointerover)="hovered.set(true)"
    (pointerout)="hovered.set(false)"
    (beforeRender)="onBeforeRender($event.object)"
>
    <ngt-box-geometry />
    <ngt-mesh-standard-material [color]="hovered() ? 'darkred' : 'orange'" />
</ngt-mesh>
```

</TabItem>

</Tabs>

:::caution

-   NGT requires Angular 16+ for Signal APIs
-   All examples will be written with Signal APIs, Standalone APIs, and `inject()`
-   HTML code snippets will be put in separate `.html` files for better syntax highlighting where needed

:::
